我們這裡有一些很酷的貨櫃要來看看嗎~
圖片來源:Docker (@Docker) / Twitter
前一篇以最簡單的 nodePort Service 公開服務,今天來更仔細的看看 Service
Pod 生命週期短,每次重新部署後都會重新分配一個內部 ip,而且 Pod 在啟動時才會被分配到 ip,沒辦法寫死綁定連線位置
Pod 在被斷定為 unhealthy 或是 Deployment 要升級版本都會直接把 Pod 砍掉,
幫可憐豆莢 QQ
所以 Kubernetes 就提供了 Service 來解決這些問題
以一個 web 架構為例
Service type 分為四種
ClusterIP
: 最基本的 Service,自動分配一個 cluster IP 給 Service 供內部使用NodePort
: 在所有 Node 上開 Port 供 cluster 外部使用,Port 範圍限定 30000~32768LoadBalancer
: 有一個外部的 LoadBalancer 會透過配發 ip 將流量導向 cluster 內部的 Service,但只有雲端平台有內建這種 LoadBalancer...ExternalName
: 將外部服務包裝成 Service 給 cluster 內部使用,會傳 CNAME record 給 externalName
DNS接著會以使用方式來分類講解不同的 Type
一般 ClusterIP Service 只能在 cluster 內部使用,那要怎麼將 Service 發佈到 cluster 外?
方法大致上分三種:
根據 Service nodePort 的設定會在所有 Node 上開出同樣的 port
30000-32767
--nodeport-addresses
<NodeIP>:nodePort
,或是在 cluster 使用內部 ip 搭配原始 Service port<ClusterIP>:port
apiVersion: v1
kind: Service
metadata:
name: test-service1
namespace: test
spec:
type: NodePort
selector:
name: test-pod
ports:
- name: foo
port: 80
targetPort: 80
nodePort: 30080
雲端平台會提供 cluster 外部的 LoadBalancer,因為 NodePort Service 依賴 Node 需要外部的分流導向,雲端的 LoadBalancer 就提供了 Node 之間的附載平衡
Service 還有一種 Type ExternalName ,用來將外部服務轉換成內部的 DNS 方便內部的使用
例如:
我想要接到 opendata 中央氣象局的 api
apiVersion: v1
kind: Service
metadata:
name: opendata-api
namespace: test
spec:
type: ExternalName
externalName: opendata.cwb.gov.tw
ports:
- port: 443
這樣 cluster 內部就能透過 https://opendata-api.test.svc.cluster.local/api
存取到 https://opendata.cwb.gov.tw/api
接著來看看 Service 和 Pod 之間的聯繫~
先來簡單架設個 Pod 和 Service 觀察...
完整檔案到 github Day 15 - test-service.yaml 上參考
在建立 Pod 的時候自動將 Service 相關設定傳進 container 內部使用 env 儲存
可以看到 Pod env 傳入的設定:
$ kubectl exec -n test test-pod1 -- env | sort
HOME=/root
HOSTNAME=test-pod1
KUBERNETES_PORT_443_TCP_ADDR=192.168.192.1
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP=tcp://192.168.192.1:443
KUBERNETES_PORT=tcp://192.168.192.1:443
KUBERNETES_SERVICE_HOST=192.168.192.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
NGINX_VERSION=1.23.1
NJS_VERSION=0.7.6
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PKG_RELEASE=1~bullseye
TEST_SERVICE1_PORT_80_TCP_ADDR=192.168.195.169
TEST_SERVICE1_PORT_80_TCP_PORT=80
TEST_SERVICE1_PORT_80_TCP_PROTO=tcp
TEST_SERVICE1_PORT_80_TCP=tcp://192.168.195.169:80
TEST_SERVICE1_PORT=tcp://192.168.195.169:80
TEST_SERVICE1_SERVICE_HOST=192.168.195.169
TEST_SERVICE1_SERVICE_PORT=80
測試看看 Service ~
$ kubectl exec -n test test-pod1 -- sh -c 'curl -s http:// $TEST_SERVICE1_PORT_80_TCP_ADDR'
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
在 Kubernetes 安裝 CoreDNS plugin (預設已安裝),CoreDNS 會協助處理 cluster 內部的 DNS 服務
可以在 Pod 查看 /etc/resolv.conf
$ kubectl exec -n test test-pod1 -- cat /etc/resolv.conf
nameserver 192.168.192.10
search test.svc.cluster.local svc.cluster.local cluster.local external.dns.tw
options ndots:5
nameserver
對應到 kube-dns Service ipkubectl get svc -n kube-system kube-dns
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 192.168.192.10 <none> 53/UDP,53/TCP,9153/TCP 45h
search
cluster.local
對應到 kubelet-config clusterDomain$ kubectl get cm -n kube-system kubelet-config -o yaml | grep clusterDomain
clusterDomain: cluster.local
Pod 可使用 FQDN svc.cluster.local
存取 cluster 內部的 Service
# FQDN
$ kubectl exec -n test test-pod1 -- curl http://test-service1.test.svc.cluster.local
# 同一個 cluster 可省略 cluster domain
$ kubectl exec -n test test-pod1 -- curl http://test-service1.test
# 同一個 namespace 可省略
$ kubectl exec -n test test-pod1 -- curl http://test-service1
Pod 為實體 ip,Service 為虛擬 ip。
kube-proxy 透過iptables
設定將 Service 虛擬 ip 轉派到對應 Pod 實體 ip。
Service IP addresses | Kubernetes
明天在繼續介紹基於 Service 的 resource Ingress~